import os
from datetime import datetime
from scipy.fft import fft
import numpy as np
import pandas as pd
import matplotlib.pyplot as plt
from DWDataReader import DWDataReader
from util.fileManger import upload_file, download_file

from scipy.signal import stft
import pywt

# 获取Excel数据
def getDxdData(dataUrl: str):
    url = ''
    return url


# 获取通道列表 []
# 配置
# ("index", c_int),
# ("name", c_char * 100),
# ("unit", c_char * 20),
# ("description", c_char * 200),
# ("color", c_uint),
# ("array_size", c_int),
# ("data_type", c_int)
def getChList(dataUrl: str):
    return DWDataReader.get_ch_list(dataUrl)

def data_transform(data_path: str):
    # 0.加载网络文件
    # 1.读取本地文件
    data = DWDataReader.get_dxd_data(data_path)

    # 转换为 DataFrame
    transformed_data = []
    for channel, samples in data.items():
        for sample in samples:
            transformed_data.append({
                "Time": sample["Time"],
                "Value": sample["Value"],
                "channel_name": channel
            })
    df = pd.DataFrame(transformed_data)
    return df

# 基本统计量，用于数值展示
def compute_basic(df):
    time_stats = df.groupby('channel_name').agg(
        mean=('Value', 'mean'),
        max=('Value', 'max'),
        min=('Value', 'min'),
        peak_to_peak=('Value', lambda x: x.max() - x.min())
    )
    return time_stats

# 时域数据：计算统计值均值、方差，提取数据时域特征
def compute_time_features(df):
    """计算时域统计特征"""
    # 基本统计量
    time_stats = compute_basic(df)
    # 过零率计算（添加阈值避免噪声误判）
    threshold = 1e-8  # 根据实际信号调整阈值
    df['sign'] = np.sign(df['Value'])
    df['crossing'] = (df['sign'] * df['sign'].shift(1) < 0) & (np.abs(df['Value']) > threshold)
    zcr = df.groupby('channel_name')['crossing'].mean()

    time_stats['zero_crossing_rate'] = zcr
    return time_stats

# 傅里叶变换，借助的这个库：from scipy.fft import fft
# 频域数据：应用傅里叶变换通过将信号转换到频域来分析其频率成分，提取数据频域特征
def compute_fft_features(df):
    fft_results = {}
    for channel, group in df.groupby('channel_name'):
        result = compute_fft_results(group)
        if result:
            fft_results[channel] = result
    print("\n频域特征:\n", fft_results)


def compute_fft_results(group, sampling_rate=10000):
    """计算频域结果"""
    values = group['Value'].values
    n = len(values)
    if n < 2:
        return None  # 跳过数据不足的通道

    fft_values = fft(values)
    freqs = np.fft.fftfreq(n, d=1 / sampling_rate)
    psd = (np.abs(fft_values) ** 2) / n
    dominant_freq = freqs[np.argmax(psd)]

    return {
        'dominant_frequency': dominant_freq,
        'psd': psd.tolist()
    }

# 小波变换

# 短时傅里叶变换

# 滤波图像生成


# 脉动量计算 RMS

# 紊流度计算

# 快速傅里叶变换

#

# 时频域特征分析和提取：结合时域和频域的信息，应用小波变换、短时傅里叶变换，提取数据时频域特征；
def compute_time_freq_features(group, sampling_rate=10000):
    """计算时频域特征"""
    values = group['Value'].values
    n = len(values)
    if n < 256:  # STFT 需要足够的数据长度
        return None

    # STFT
    f, t, Z = stft(values, fs=sampling_rate, nperseg=256, noverlap=128)
    stft_psd = np.abs(Z) ** 2

    # 小波变换
    max_level = min(int(np.floor(np.log2(n))), 5) if n > 1 else 0  # 限制最大层数
    coeffs = pywt.wavedec(values, 'db4', level=max_level)
    energy = [np.sum(np.abs(c) ** 2) for c in coeffs]
    scales = [2 ** (level + 1) for level in range(max_level)]  # 生成尺度列表

    return {
        'stft_psd': stft_psd.tolist(),
        'wavelet_energy': energy,
        'wavelet_scales': scales
    }

# 时间顺序检索：我觉得这一块得用时序数据库才能检索。应用时间戳索引，确保数据按照时间顺序存储，便于检索和分析。


# 获取时域信号波形图
def dataReadTimeDomainWaveform(dataUrl: str):
    # 1.下载文件到本地
    data_path = download_file(url=dataUrl)
    # 2.读取文件
    data = DWDataReader.get_dxd_data(data_path)

    # 转换为 DataFrame
    transformed_data = []
    for channel, samples in data.items():
        for sample in samples:
            transformed_data.append({
                "Time": sample["Time"],
                "Value": sample["Value"],
                "channel_name": channel
            })
    df = pd.DataFrame(transformed_data)

    # 时域信号波形图
    plt.figure(figsize=(12, 6))
    for channel in df['channel_name'].unique()[:1]:  # 仅展示前1个通道避免拥挤
        channel_df = df[df['channel_name'] == channel]
        plt.plot(channel_df['Time'], channel_df['Value'], label=channel)
    plt.title("Time Domain Waveform")  # 英文标题
    plt.xlabel("Time (s)")  # 英文坐标标签
    plt.ylabel("Amplitude")
    plt.legend()
    plt.grid(True)

    # 保存文件
    timestamp = datetime.now().strftime("%Y_%m_%d_%H%M%S")
    data_filename = os.path.splitext(os.path.basename(data_path))[0]
    save_dir = os.path.join("temp", "result")
    os.makedirs(save_dir, exist_ok=True)
    save_path = os.path.join(
        save_dir,
        f"Time--Domain--Waveform--{timestamp}--{data_filename}.png"
    )
    plt.savefig(save_path, dpi=300, bbox_inches='tight')

    # 上传文件
    result_url = upload_file(save_path)
    # 清空临时文件
    return result_url

def test_ch_list(data_path):
    ch_list = getChList(data_path)
    for i in range(0, len(ch_list)):
        # basic channel properties
        print("************************************************")
        print("Channel #%d" % (i + 1))
        print("************************************************")
        print("Index: %d" % ch_list[i].index)
        print("Name: %s" % ch_list[i].name.decode())
        print("Unit: %s" % ch_list[i].unit.decode())
        print("Description: %s" % ch_list[i].description.decode())

def test_time_domain_wave(data_path):
    TimeDomainWaveformResult = dataReadTimeDomainWaveform(data_path)
    print(TimeDomainWaveformResult)

def test_data_transform(dataPath):
    df = data_transform(dataPath)
    # print(df)
    return df

def test_compute_basic(dataPath: str):
    df = test_data_transform(dataPath)
    time_stats = compute_basic(df)
    print(time_stats)

def test_compute_time_features(dataPath: str):
    df = test_data_transform(dataPath)
    time_stats = compute_time_features(df)
    print(time_stats)

def test_compute_fft_features(dataPath: str):
    df = test_data_transform(dataPath)
    fft_results = compute_fft_features(df)
    print(fft_results)

def main():
    # 加载数据
    data_path = "temp/data/Test_2024_08_21_095324.dxd"
    # test_time_domain_wave()
    # test_ch_list(data_path)
    # test_data_transform(data_path)
    # test_compute_basic(data_path)
    # test_compute_time_features(data_path)
    test_compute_fft_features(data_path)

if __name__ == "__main__":
    main()